package com.android.sq.zouqi.pushservice;

import java.io.IOException;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import com.android.sq.zouqi.Constants;
import com.android.sq.zouqi.R;
import com.android.sq.zouqi.bdmap.BMapApp;
import com.android.sq.zouqi.main.pScrMain;
import com.ibm.mqtt.IMqttClient;
import com.ibm.mqtt.MqttClient;
import com.ibm.mqtt.MqttException;
import com.ibm.mqtt.MqttPersistence;
import com.ibm.mqtt.MqttPersistenceException;
import com.ibm.mqtt.MqttSimpleCallback;

/*
 * 修改了Share的TAG
 */
/* 
 * PushService that does all of the work.
 * Most of the logic is borrowed from KeepAliveService.
 * http://code.google.com/p/android-random/source/browse/trunk/TestKeepAlive/src/org/devtcg/demo/keepalive/KeepAliveService.java?r=219
 */
public class PushService extends Service
{
	BMapApp app;
	// this is the log tag
	public static final String		TAG = "PushService";

	// the IP address, where your MQTT broker is running.
	private static final String		MQTT_HOST = "192.168.1.100";
	//private static final String 	MQTT_HOST = "10.42.43.1";
	//private static final String 	MQTT_HOST ="test.mosquitto.org";
	//private static final String 	MQTT_HOST = "localhost";
	
	// the port at which the broker is running. 
	// 代理服务器运行的端口
	private static int				MQTT_BROKER_PORT_NUM      = 1883;
	// Let's not use the MQTT persistence.
	// 无需用到MQTT的持久链接
	private static MqttPersistence	MQTT_PERSISTENCE          = null;
	// We don't need to remember any state between the connections, so we use a clean start. 
	// 在链接中无需记住任何状态，所以我们用一个纯净的开始
	private static boolean			MQTT_CLEAN_START          = false;	// e.g true
	// Let's set the internal keep alive for MQTT to 15 mins. 
	// I haven't tested this value much. It could probably be increased.
	// 设置内置生存期为15分钟。我对这个值测试不多，它可能应该被增加
	private static short			MQTT_KEEP_ALIVE           = 30;		// e.g 60 * 15;
	// Set quality of services to 0 (at most once delivery), since we don't want push notifications 
	// arrive more than once. However, this means that some messages might get lost (delivery is not guaranteed)
	// 设置mqtt的服务质量为0（也就是一次投递），因为我们不想要推送通知多于一次。然而，这也意味着有些消息可能被丢弃。
	private static int[]			MQTT_QUALITIES_OF_SERVICE = { 0 } ;	// e.g 0, value of {0, 1, 2}
	private static int				MQTT_QUALITY_OF_SERVICE   = 0;		// e.g 0
	// The broker should not retain any messages.
	// 代理服务器不应该保留任何消息
	private static boolean			MQTT_RETAINED_PUBLISH     = true;	// e.g false
		
	// MQTT client ID, which is given the broker. In this example, I also use this for the topic header. 
	// You can use this to run push notifications for multiple apps with one MQTT broker. 
	// 设置MQTT客户端的ID，需要传递给代理服务器。在这个例子中，我也用它作为主题的头部。
	// 你能用这个id为多应用运行推送消息在一个代理服务器。
	public static String			MQTT_CLIENT_ID 			  = "zouqi_client";
	public static String			MQTT_TOPIC 				  = "zouqi";

	// These are the actions for the service (name are descriptive enough)
	private static final String		ACTION_START = MQTT_CLIENT_ID + ".START";
	private static final String		ACTION_STOP = MQTT_CLIENT_ID + ".STOP";
	private static final String		ACTION_KEEPALIVE = MQTT_CLIENT_ID + ".KEEP_ALIVE";
	private static final String		ACTION_RECONNECT = MQTT_CLIENT_ID + ".RECONNECT";
	
	// Connection log for the push service. Good for debugging.
	//private ConnectionLog 			mLog;
	
	// Connectivity manager to determining, when the phone loses connection
	// 链接管理器，当手机失去网络链接
	private ConnectivityManager		mConnMan;
	// 通知管理器用于显示到达的通知
	// Notification manager to displaying arrived push notifications 
	private NotificationManager		mNotifMan;

	// Whether or not the service has been started.	
	// 是否这个服务已经开始
	private boolean 				mStarted;

	// This the application level keep-alive interval, that is used by the AlarmManager
	// to keep the connection active, even when the device goes to sleep.
	// 
	private static final long		KEEP_ALIVE_INTERVAL = 1000 * 60 * 28;

	// Retry intervals, when the connection is lost.
	// 重试间隔，当链接丢失时
	private static final long		INITIAL_RETRY_INTERVAL = 1000 * 10;
	private static final long		MAXIMUM_RETRY_INTERVAL = 1000 * 60 * 30;

	// Preferences instance 
	private SharedPreferences 		mPrefs;
	// We store in the preferences, whether or not the service has been started
	public static final String		PREF_STARTED = "isStarted";
	// We also store the deviceID (target)
	public static final String		PREF_DEVICE_ID = "deviceID";
	// We store the last retry interval
	public static final String		PREF_RETRY = "retryInterval";

	// Notification title
	//public static String			NOTIF_TITLE = "Tokudu";
	public static String 			NOTIF_TITLE = "Dadanihei";
	// Notification id
	// 通知id
	private static final int		NOTIF_CONNECTED = 0;	
		
	// This is the instance of an MQTT connection.
	// 这个是MQTT的链接实例
	private static MQTTConnection	mConnection;
	private long					mStartTime;
	

	public static Handler handler;			// 对应于pScrMain 的handler，用于活动 好友 历史的事件消息传递
	
	// Static method to start the service
	public static void actionStart(Context ctx) {
		Intent i = new Intent(ctx, PushService.class);
		i.setAction(ACTION_START);
		ctx.startService(i);
		Log.e(TAG, "开启MQTT服务");
	}

	// Static method to stop the service
	public static void actionStop(Context ctx) {
		Log.e(TAG, "关闭MQTT服务");
		Intent i = new Intent(ctx, PushService.class);
		i.setAction(ACTION_STOP);
		ctx.startService(i);
	}
	
	// Static method to send a keep alive message
	public static void actionPing(Context ctx) {
		Intent i = new Intent(ctx, PushService.class);
		i.setAction(ACTION_KEEPALIVE);
		ctx.startService(i);
	}

	/*
	 * 自己添加，用于订阅主题
	 */
	public static void actionSubTopics(String topic) {
		try {
			if (mConnection == null) {
				Log.e(TAG, "actionSubTopics->mConnection is null");
			}
			mConnection.subscribeToTopic(topic);
		} catch (MqttException e){
			e.printStackTrace();
		}
	}
	
	/*
	 * 自己添加，用于退订主题
	 */
	public static void actionUnsubTopics(String topic) {
		try {
			mConnection.unsubscribeToTopic(topic);
		} catch (MqttException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/*
	 * 自己添加，用于给某个主题发送消息
	 */
	public static void actionSendMsgToTopic(String topic, String msg) {
		try {
			mConnection.publishToTopic(topic, msg);
		} catch(MqttException e) {
			e.printStackTrace();
		}
	}
	@Override
	public void onCreate() {
		super.onCreate();
		
		app = (BMapApp) this.getApplication();
		this.handler = app.handler;
		
		handler.sendEmptyMessage(100);
		
		Log.e(TAG, "推送服务onCreate - Host = " + MQTT_HOST);
		mStartTime = System.currentTimeMillis();

		/*try {
			mLog = new ConnectionLog();
			Log.i(TAG, "Opened log at " + mLog.getPath());
		} catch (IOException e) {
			Log.e(TAG, "Failed to open log", e);
		}*/

		// Get instances of preferences, connectivity manager and notification manager
		//mPrefs = getSharedPreferences(TAG, MODE_PRIVATE);
		mPrefs = this.getApplicationContext().getSharedPreferences(Constants.SP_USER_INFO, Context.MODE_PRIVATE);
		int user_id = mPrefs.getInt(Constants.SP_USER_ID, 0);
		Log.e("PushService", "just now user_id = " + user_id);
		mConnMan = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);
		mNotifMan = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
	
		/* If our process was reaped by the system for any reason we need
		 * to restore our state with merely a call to onCreate.  We record
		 * the last "started" value and restore it here if necessary. */
		handleCrashedService();
	}
	
	// This method does any necessary clean-up need in case the server has been destroyed by the system
	// and then restarted
	private void handleCrashedService() {
		if (wasStarted() == true) {
			log("Handling crashed service...");
			 // stop the keep alives
			stopKeepAlives(); 
				
			// Do a clean start
			start();
		}
	}
	
	@Override
	public void onDestroy() {
		log("Service destroyed (started=" + mStarted + ")");

		// Stop the services, if it has been started
		if (mStarted == true) {
			stop();
		}
		
		/*try {
			if (mLog != null)
				mLog.close();
		} catch (IOException e) {}	*/	
	}
	
	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
		log("Service started with intent=" + intent);

		// Do an appropriate action based on the intent.
		if (intent.getAction().equals(ACTION_STOP) == true) {
			log("intent action = action_stop");
			stop();
			stopSelf();
		} else if (intent.getAction().equals(ACTION_START) == true) {
			log("intent actoin = action_start");
			start();
		} else if (intent.getAction().equals(ACTION_KEEPALIVE) == true) {
			log("intent action = action_keepalive");
			keepAlive();
		} else if (intent.getAction().equals(ACTION_RECONNECT) == true) {
			log("intent action = action_reconnect");
			if (isNetworkAvailable()) {
				reconnectIfNecessary();
			}
		}
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	// log helper function
	private void log(String message) {
		log(message, null);
	}
	private void log(String message, Throwable e) {
		if (e != null) {
			Log.e(TAG, message, e);
			
		} else {
			Log.i(TAG, message);			
		}
		
		/*if (mLog != null)
		{
			try {
				mLog.println(message);
			} catch (IOException ex) {}
		}	*/	
	}
	
	// Reads whether or not the service has been started from the preferences
	private boolean wasStarted() {
		return mPrefs.getBoolean(PREF_STARTED, false);
	}

	// Sets whether or not the services has been started in the preferences.
	private void setStarted(boolean started) {
		mPrefs.edit().putBoolean(PREF_STARTED, started).commit();		
		mStarted = started;
	}

	private synchronized void start() {
		log("Starting service...");
		
		// Do nothing, if the service is already running.
		if (mStarted == true) {
			Log.w(TAG, "Attempt to start connection that is already active");
			return;
		}
		
		// Establish an MQTT connection
		connect();
		
		// Register a connectivity listener
		// 注册 网络管理器 的消息接受者
		registerReceiver(mConnectivityChanged, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
	}

	private synchronized void stop() {
		// Do nothing, if the service is not running.
		if (mStarted == false) {
			Log.w(TAG, "Attempt to stop connection not active.");
			return;
		}

		// Save stopped state in the preferences
		setStarted(false);

		// Remove the connectivity receiver
		unregisterReceiver(mConnectivityChanged);
		// Any existing reconnect timers should be removed, since we explicitly stopping the service.
		cancelReconnect();
		log("cancelReconnect");
		// Destroy the MQTT connection if there is onemConnection
		if (mConnection != null) {
			mConnection.disconnect();
			mConnection = null;
			log("mConnection = null");
		}
	}
	
	// 
	private synchronized void connect() {		
		log("Connecting...");
		// fetch the device ID from the preferences.
		//String deviceID = mPrefs.getString(PREF_DEVICE_ID, null);
		int deviceID = mPrefs.getInt(Constants.SP_USER_ID, 0);
		log("Connecting...pref_device_id=" + deviceID);
		// Create a new connection only if the device id is not NULL
		if (deviceID == 0) {
			log("Device ID not found.");
		} else {
			try {
				log("MqttException:开始初始化mConnection");
				mConnection = new MQTTConnection(MQTT_HOST, ""+deviceID);
			} catch (MqttException e) {
				// Schedule a reconnect, if we failed to connect
				log("MqttException: " + (e.getMessage() != null ? e.getMessage() : "NULL"));
	        	if (isNetworkAvailable()) {
	        		scheduleReconnect(mStartTime);
	        	}
			}
			setStarted(true);
		}
	}

	private synchronized void keepAlive() {
		try {
			// Send a keep alive, if there is a connection.
			if (mStarted == true && mConnection != null) {
				mConnection.sendKeepAlive();
			}
		} catch (MqttException e) {
			log("MqttException: " + (e.getMessage() != null ? e.getMessage(): "NULL"), e);
			mConnection.disconnect();
			mConnection = null;
			cancelReconnect();
		}
	}

	// Schedule application level keep-alives using the AlarmManager
	private void startKeepAlives() {
		log("start Keep Alives alarmManager");
		Intent i = new Intent();
		i.setClass(this, PushService.class);
		i.setAction(ACTION_KEEPALIVE);
		PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
		AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
		alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
		  System.currentTimeMillis() + KEEP_ALIVE_INTERVAL,
		  KEEP_ALIVE_INTERVAL, pi);
	}

	// Remove all scheduled keep alives
	private void stopKeepAlives() {
		log("stop keep alives");
		Intent i = new Intent();
		i.setClass(this, PushService.class);
		i.setAction(ACTION_KEEPALIVE);
		PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
		AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
		alarmMgr.cancel(pi);
	}

	// We schedule a reconnect based on the starttime of the service
	public void scheduleReconnect(long startTime) {
		// the last keep-alive interval
		long interval = mPrefs.getLong(PREF_RETRY, INITIAL_RETRY_INTERVAL);

		// Calculate the elapsed time since the start
		long now = System.currentTimeMillis();
		long elapsed = now - startTime;


		// Set an appropriate interval based on the elapsed time since start 
		if (elapsed < interval) {
			interval = Math.min(interval * 4, MAXIMUM_RETRY_INTERVAL);
		} else {
			interval = INITIAL_RETRY_INTERVAL;
		}
		
		log("Rescheduling connection in " + interval + "ms.");

		// Save the new internval
		mPrefs.edit().putLong(PREF_RETRY, interval).commit();

		// Schedule a reconnect using the alarm manager.
		Intent i = new Intent();
		i.setClass(this, PushService.class);
		i.setAction(ACTION_RECONNECT);
		PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
		AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
		alarmMgr.set(AlarmManager.RTC_WAKEUP, now + interval, pi);
	}
	
	// Remove the scheduled reconnect
	public void cancelReconnect() {
		Intent i = new Intent();
		i.setClass(this, PushService.class);
		i.setAction(ACTION_RECONNECT);
		PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
		AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
		alarmMgr.cancel(pi);
	}
	
	private synchronized void reconnectIfNecessary() {		
		if (mStarted == true && mConnection == null) {
			log("Reconnecting...");
			connect();
		}
	}

	// This receiver listeners for network changes and updates the MQTT connection
	// accordingly
	private BroadcastReceiver mConnectivityChanged = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			log("onReceive");
			// Get network info
			NetworkInfo info = (NetworkInfo)intent.getParcelableExtra (ConnectivityManager.EXTRA_NETWORK_INFO);
			
			// Is there connectivity?
			boolean hasConnectivity = (info != null && info.isConnected()) ? true : false;

			log("Connectivity changed: connected=" + hasConnectivity);

			if (hasConnectivity) {
				reconnectIfNecessary();
			} else if (mConnection != null) {
				// if there no connectivity, make sure MQTT connection is destroyed
				mConnection.disconnect();
				cancelReconnect();
				mConnection = null;
			}
		}
	};
	
	// Display the topbar notification
	private void showNotification(String text) {
		Notification n = new Notification();
				
		n.flags |= Notification.FLAG_SHOW_LIGHTS;
      	n.flags |= Notification.FLAG_AUTO_CANCEL;

        n.defaults = Notification.DEFAULT_ALL;
      	
		n.icon = R.drawable.icon;
		n.when = System.currentTimeMillis();

		// Simply open the parent activity
		// 此处是点击推送消息的界面切换
		PendingIntent pi = PendingIntent.getActivity(this, 0, new Intent(this, pScrMain.class), 0);
		
		
		// Change the name of the notification here
		n.setLatestEventInfo(this, NOTIF_TITLE, text, pi);
		
		Log.e(TAG, "showNotification");
		mNotifMan.notify(NOTIF_CONNECTED, n);
	}
	
	// Check if we are online
	private boolean isNetworkAvailable() {
		NetworkInfo info = mConnMan.getActiveNetworkInfo();
		if (info == null) {
			return false;
		}
		return info.isConnected();
	}
	
	// This inner class is a wrapper on top of MQTT client.
	private class MQTTConnection implements MqttSimpleCallback {
		IMqttClient mqttClient = null;
		int user_id = 0;
		// Creates a new connection given the broker address and initial topic
		public MQTTConnection(String brokerHostName, String initTopic) throws MqttException {
			// Create connection spec  tcp://192.168.1.187@1883
	    	String mqttConnSpec = "tcp://" + brokerHostName + "@" + MQTT_BROKER_PORT_NUM;
	        	// Create the client and connect
	        	mqttClient = MqttClient.createMqttClient(mqttConnSpec, MQTT_PERSISTENCE);
	        	// tokudu/2523kl3459askf  手机设备ID:2523kl3459askf
	        	user_id = mPrefs.getInt(Constants.SP_USER_ID, 0);
	        	Log.e("PushService", "user_id = " + user_id);
	        	String clientID = MQTT_CLIENT_ID + "/" + user_id;
	        	log("clientID = " + clientID);
	        	mqttClient.connect(clientID, MQTT_CLEAN_START, MQTT_KEEP_ALIVE);

		        // register this client app has being able to receive messages
				mqttClient.registerSimpleHandler(this);
				// Subscribe to an initial topic, which is combination of client ID and device ID.
				// tokudu/2523kl3459askf/
				
				//initTopic = MQTT_TOPIC + "/" + initTopic;
				//initTopic = MQTT_TOPIC;
				
				
				initTopic = MQTT_TOPIC + "/user_" + user_id;
				log("initTopic = " + initTopic); //subscribeToTopic(initTopic);
				
				{
					if ((mqttClient == null) || (mqttClient.isConnected() == false)) {
						// quick sanity check - don't try and subscribe if we don't have
						//  a connection
						log("Connection error" + "No connection");	
					} else {									
						String[] topics = { initTopic };
						mqttClient.subscribe(topics, MQTT_QUALITIES_OF_SERVICE);
						log(initTopic + " - 订阅者发送主题给broker");
					}
				}
		
				log("Connection established to " + brokerHostName + " on topic " + initTopic);
		
				// Save start time 
				mStartTime = System.currentTimeMillis();
				// Star the keep-alives 
				startKeepAlives();				        
		}
		
		// Disconnect
		public void disconnect() {
			try {			
				stopKeepAlives();
				mqttClient.disconnect();
			} catch (MqttPersistenceException e) {
				log("MqttException" + (e.getMessage() != null? e.getMessage():" NULL"), e);
			}
		}
		/*
		 * Send a request to the message broker to be sent messages published with 
		 *  the specified topic name. Wildcards are allowed.	
		 */
		private void subscribeToTopic(String topicName) throws MqttException {
			if ((mqttClient == null) || (mqttClient.isConnected() == false)) {
				// quick sanity check - don't try and subscribe if we don't have
				//  a connection
				log("Connection error" + "No connection");	
			} else {									
				String[] topics = { topicName };
				mqttClient.subscribe(topics, MQTT_QUALITIES_OF_SERVICE);
				log(topicName + " - 订阅者发送主题给broker");
			}
		}
		
		public void unsubscribeToTopic(String topicName) throws MqttException {
			if (mqttClient == null || mqttClient.isConnected() == false) {
				log("unsubscribe topics - Connection error No connection");
			} else {
				String[] topic = {topicName};
				mqttClient.unsubscribe(topic);
				log("unsubscribe topic - " + topicName);
				log("以后’" + topic[0] + "‘的消息再也收不到了...");
			}
		}
		/*
		 * Sends a message to the message broker, requesting that it be published
		 *  to the specified topic.
		 */
		private void publishToTopic(String topicName, String message) throws MqttException {		
			if ((mqttClient == null) || (mqttClient.isConnected() == false)) {
				// quick sanity check - don't try and publish if we don't have
				//  a connection				
				log("No connection to public to");		
			} else {
				mqttClient.publish(topicName, 
								   message.getBytes(),
								   MQTT_QUALITY_OF_SERVICE, 
								   MQTT_RETAINED_PUBLISH);
				
			}
		}		
		
		/*
		 * Called if the application loses it's connection to the message broker.
		 */
		@Override
		public void connectionLost() throws Exception {
			log("Loss of connection" + "connection downed");
			stopKeepAlives();
			// null itself
			mConnection = null;
			if (isNetworkAvailable() == true) {
				reconnectIfNecessary();	
			}
		}		
		
		/*
		 * Called when we receive a message from the message broker. 
		 */
		@Override
		public void publishArrived(String topicName, byte[] payload, int qos, boolean retained) {
			// Show a notification
			String msg = new String(payload);
			Log.e("PushService", "收到消息" + topicName + " = " + msg);
			/*
			 * 根据所收到消息的主题不同，向pScrMain发送不同的消息以处理
			 */
			// 用户相关的zouqi/user_id消息
			if (topicName.equals(MQTT_TOPIC + "/user_" + mPrefs.getInt(Constants.SP_USER_ID, 0))) {
				int flag_index = msg.indexOf(":");
				String msg_type_str = msg.substring(0, flag_index);
				int msg_type = Integer.parseInt(msg_type_str);
				String msg_content = msg.substring(flag_index + 1);
				
				//Log.e("PushService", "publish arrived msg_type " + msg_type + "; msg_content = " + msg_content);
				if (msg_type == Constants.PUSH_MSG_TYPE_NEW_EVENT) {
					// msg_content 的值 = 新活动的系统id，
					// 这样用户再订阅zouqi/event_id的内容
					// 即得到新活动邀请，向pScrMain发送相应消息，刷新活动标签页内容
					//Log.e(TAG, "收到的消息类型：new_event");
					Message h_msg = new Message();
					h_msg.what = Constants.notify_new_event_signal;
					h_msg.obj = msg_content;
					handler.handleMessage(h_msg);
					//Log.e(TAG, "发送通知给通知栏之前");
					showNotification("您有新的活动邀请!");
				} /*else if (msg_type.equals("new_friend")) {
					// 当收到新的好友邀请时，向pScrMain发送相应的消息，刷新好友标签页内容
					//handler.sendEmptyMessage(Constants.notify_new_friend_signal);
					showNotification("您有新的好友想要加您为好友!");
				}*/
				//handler.sendEmptyMessage(pScrMain.notify_show_history_signal);
			}
			/*
			 * 活动消息有三类
			 * 好友的方位信息：		   zouqi/event_id/geo - 好友id:latitude:longitude
			 *         群聊：		  zouqi/event_id/chat - 好友id:聊天内容
			 *      活动修改：		zouqi/event_id/modify - 修改了什么？
			 */
			else if (topicName.contains("geo")) {		
				/*
				 * 这个消息用来向pScrEventMap发送参与人的地理信息的
				 * 因为这里将收取到一个主题的消息(主题， 消息)(zouqi/event_id/geo, 好友id:latitude,longitude)
				 */
				int firstNumIndex = topicName.indexOf("_")+1;	// 第一个数字的索引
				int endNumIndex = topicName.indexOf("g")-1;		// 第二个斜杠的索引
				int event_id = Integer.parseInt(topicName.substring(firstNumIndex, endNumIndex));
				//Log.e(TAG, "主题GEO，关于活动" + event_id);
				int activityName = app.getActivityName();
				int curEventId = (Integer)app.getActivityInfo();
				
				// 保证当前运行的Activity是pScrEventMap，而且是展示活动*的信息
				if (activityName == Constants.ACTIVTIY_pScrEventMap 
						|| event_id == curEventId) {
					//Log.e(TAG, "是当前这个活动");
					Message h_msg = new Message();
					h_msg.what = Constants.notify_participant_cur_location;
					h_msg.obj = msg;
					handler.sendMessage(h_msg);
				}
			} else if (topicName.contains("chat")) {
				// 先放着，当做到聊天这块就能添加了
			} else if (topicName.contains("modify")) {
				// 也先放着
			}
			
			//showNotification(msg);	
			//log("Got message: " + msg);
		}   
		
		public void sendKeepAlive() throws MqttException {
			log("Sending keep alive");
			// publish to a keep-alive topic
			//publishToTopic(MQTT_CLIENT_ID + "/keepalive", mPrefs.getString(PREF_DEVICE_ID, ""));
			publishToTopic(MQTT_TOPIC + "/keepalive", mPrefs.getString(PREF_DEVICE_ID, ""));
		}		
	}
}